using System;
using Microsoft.SPOT;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
using NetduinoHappyHour.Util;

namespace NetduinoHappyHour.Hardware
{
    /// <summary>
    /// CheckBattery reads battery voltage by analogInput and normalizes to real battery voltage
    /// Uses GPIO_PIN_A3
    /// </summary>
    public class CheckBattery : IExecutable, IDisposable
    {
        private SecretLabs.NETMF.Hardware.AnalogInput _pot = null;

        /// <summary>
        /// The measured Value
        /// </summary>
        private Double _value = 0.0;

        /// <summary>
        /// If set to true, the CheckBattery will try to display the measured Value on LCD
        /// </summary>
        private bool _displayValue = false;

        /// <summary>
        /// The multiplier reflects the hardware requirements. The Netduino AnalogInput is able to read 0 - 3.3 Volt 
        /// with 1024 step resolution. Due to the battery voltage of 12 Volt a voltage divider is required.
        /// </summary>
        private const double MULTIPLIER = 3.3 / 1024 * 5;

        /// <summary>
        /// Defalt Constructor, prepares to measure battery power
        /// </summary>
        public CheckBattery()
            : this(false) { }

        /// <summary>
        /// Prepares to measure battery power
        /// </summary>
        /// <param name="displayValue">If "true", Execute() will try to display Value on LCD</param>
        public CheckBattery(String displayValue)
            : this(BooleanHelper.Parse(displayValue)) { }

        /// <summary>
        /// Prepares to measure battery power
        /// </summary>
        /// <param name="displayValue">If true, Execute() will try to display Value on LCD</param>
        public CheckBattery(bool displayValue)
        {
            SystemConfig.Instance().RegisterPin(Pins.GPIO_PIN_A3, GetType().Name);
            _pot = new SecretLabs.NETMF.Hardware.AnalogInput(Pins.GPIO_PIN_A3);
            _displayValue = displayValue;
        }
        
        /// <summary>
        /// Provides the battery voltage
        /// </summary>
        public Double Value
        {
            get { return _value; }
        }

        /// <summary>
        /// Executes the measurement to determine the battery's power
        /// </summary>
        public void Execute()
        {
            int potValue = 0;
            potValue = _pot.Read();
            _value = potValue * MULTIPLIER;
            if (_displayValue)
            {
                new DisplayMessage(this.ToString()).Execute();
            }
        }

        public void Dispose()
        {
            _pot.Dispose();
            SystemConfig.Instance().DeregisterPin(Pins.GPIO_PIN_A3);
        }

        /// <summary>
        /// Returns "Battery:x.yy"
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            // F2 merans floating point to decimal digits
            return "Battery:" + _value.ToString("F2");
        }
    }
}
